#ifndef EMS_SERVICE_DISPATCH_SERVICE_H
#define EMS_SERVICE_DISPATCH_SERVICE_H

#include <atomic>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <vector>

namespace ems {
namespace service {

class DataUploader;

namespace tracker {
    class StorageChargePriceTracker;
}

// 储能调度窗口，用于限定当前策略允许的充放电行为
enum class StorageWindow {
    ChargeWindow,      // 允许充电窗口
    DischargeWindow,   // 允许放电窗口
    IdleWindow         // 禁止调整窗口
};

// 储能实时运行状态，可结合硬件反馈辅助判断
enum class StorageState {
    Charging,
    Discharging,
    Idle
};

// 调度动作编码，与指导文档中的动作定义一一对应
enum class DispatchActionCode {
    SelfUseAllPv,             // 光伏全额自用
    StoreAllPv,               // 光伏全额充电
    StorePartPv,              // 光伏部分充电
    FeedExcessPv,             // 光伏余电上网
    GridSupplyLoad,           // 市电补足负载
    StorageDischargeFull,     // 储能全功率放电
    StorageDischargeControl,  // 储能按需放电
    PauseStorageCharge,       // 暂停充电
    PauseStorageDischarge,    // 暂停放电
    IdleAll                   // 保持原状
};

// 储能设备执行指令简化：实际可执行的启停动作
enum class StorageDeviceCommand {
    None,            // 不下发储能控制
    Start,           // 启动储能运行（充/放电按策略已有动作决定）
    Stop             // 停止储能运行
};

// 调度上下文，输入来自采集/配置，输出为调度回填标志与拓展字段
// 数据映射速记（核对采集来源用）：
// 字段                    | 协议来源 | 表 / 地址 / 名称                                      | 单位 | 备注
// ------------------------|----------|-------------------------------------------------------|------|--------------------------------------------------------------
// load_power_kw           | zkzf     | EMS-遥测 · 地址100 · pcs实际总有功功率(汇总)          | kW   | 保持寄存器，长度2，系数0.01；正负号按现场充/放电约定
// storage_charge_cap_kw   | zkzf     | BMS-遥测 · 地址225/275/... · 允许充电功率(最大)       | kW   | 每簇一个点，功能码0x03/0x04，长度1；可取首簇或聚合
// storage_discharge_cap_kw| zkzf     | BMS-遥测 · 地址226/276/... · 允许放电功率(最大)       | kW   | 与充电功率同源，聚合策略须一致
// storage_soc             | zkzf     | EMS-遥测 · 地址104 · 总SOC(汇总)                      | %    | 长度2，系数0.1；簇级参考地址200/250/... 堆SOC
// storage_state           | zkzf     | BMS-遥测 · 地址202/252/... · 堆状态(0:停1:充2:放3:待4)| 枚举 | 读取后映射 StorageState，多簇按业务规则整合
// storage_window          | -        | -                                                     | -    | 由 storage_state 推导（Charging→ChargeWindow 等）
// pv_power_kw             | growatt  | Sheet2 · 地址35-36 · dc_module_pv_power               | kW   | 输入寄存器，长度2，系数0.1；DataUploader 已接入
struct DispatchContext {
    // 输入字段（采集/配置提供）
    double load_power_kw{0.0};                    // 输入：系统当前总负载功率（默认占位，成功采样后覆盖；数据源 pcs.total_active_power，古瑞瓦特寄存器3500）
    double pv_power_kw{0.0};                      // 输入：光伏瞬时输出功率（默认占位，成功采样后覆盖；数据源 pcs.dc_module_pv_power，寄存器35-36）
    double storage_charge_cap_kw{0.0};            // 输入：储能可用充电功率上限（默认占位；数据源待对接，可由BMS功率上限换算）
    double storage_discharge_cap_kw{0.0};         // 输入：储能可用放电功率上限（默认占位；数据源待对接，可由BMS功率上限换算）
    StorageWindow storage_window{StorageWindow::IdleWindow}; // 输入：当前调度窗口（默认闲置，可由采样或策略调整；由 storage_state 推导）
    StorageState storage_state{StorageState::Idle};          // 输入：储能实时状态（默认闲置，成功采样后覆盖；数据源 pcs.storage_state/BMS 堆状态）
    double storage_soc{0.0};                      // 输入：储能 SOC（默认占位，成功采样后覆盖；数据源 pcs.battery_state_of_charge，寄存器1924）
    double storage_charge_price{0.0};             // 输入：储能历史充电均价（默认占位；数据源业务结算配置/能量账本，待接入）
    double pv_feed_price{0.0};                    // 输入：光伏上网结算价（默认占位或固定值；数据源价格配置，当前为常量0.453）
    double grid_price_now{0.0};                   // 输入：市电即时电价（默认占位；数据源 TOU 配置 Config::getTimeOfUsePrice）
    double grid_price_peak{0.0};                  // 输入：当日峰段最高电价（默认占位；数据源 TOU 配置/价格服务，待写入）
    bool is_peak_period{false};                   // 输入：是否处于最高电价时段（默认占位；数据源 TOU 时段判定逻辑，待实现）
    double critical_load_kw{0.0};                 // 输入：关键负载保底功率（默认占位；数据源项目配置/策略表，待接入）

    // 输出字段（调度计算回填或采样状态）
    bool load_power_valid{false};                 // 输出：load_power_kw 是否成功采样（true 表示读取到实时负载功率，false 表示沿用占位值/采集失败）
    bool pv_power_valid{false};                   // 输出：pv_power_kw 是否成功采样（true 表示光伏功率有效，false 表示暂无有效数据）
    bool storage_charge_cap_valid{false};         // 输出：storage_charge_cap_kw 是否成功采样（true 表示获取到充电功率上限，false 表示需使用默认值）
    bool storage_discharge_cap_valid{false};      // 输出：storage_discharge_cap_kw 是否成功采样（true 表示获取到放电功率上限，false 表示需使用默认值）
    bool storage_soc_valid{false};                // 输出：storage_soc 是否成功采样（true 表示 SOC 来自最新采样，false 表示占位或超时）
    bool storage_state_valid{false};              // 输出：storage_state/storage_window 是否来自采样（true 表示实际状态映射，false 表示保持默认 Idle）
};

// 调度输出，使用动作列表表示组合策略
struct DispatchAction {
    std::vector<DispatchActionCode> actions; // 组合动作集合
    std::vector<std::string> trace;          // 决策路径标签序列
    StorageDeviceCommand storageCommand{StorageDeviceCommand::None}; // 储能执行指令
};

class DispatchService {
public:
    // 构造与析构：负责初始化默认动作并确保线程安全退出
    DispatchService();
    ~DispatchService();

    // 初始化内部缓存，待外部模块完成真实数据绑定后调用
    bool initialize();
    // 启动调度线程，按周期执行评估逻辑
    void start();
    // 停止调度线程，线程安全且可重复调用
    void stop();

    // 查询当前调度线程是否处于运行态
    bool isRunning() const { return running_; }

    // 设置数据上传器引用，用于读取缓存数据
    void setDataUploader(DataUploader* uploader) { dataUploader_ = uploader; }

    // 设置评估间隔 seconds（秒），用于调整调度实时性
    void setEvaluationInterval(int seconds);
    // 获取当前评估间隔（秒）
    int getEvaluationInterval() const { return evaluationIntervalSec_.load(); }

    // 读取最近一次调度上下文快照，供外部监控
    DispatchContext getLastContext() const;
    // 读取最近一次调度动作组合
    DispatchAction getLastAction() const;

    void setEnabled(bool enabled);
    bool isEnabled() const { return enabled_.load(); }
    
    // 获取充电价格跟踪器（用于查询日夜平均价）
    tracker::StorageChargePriceTracker* getChargePriceTracker() { return chargePriceTracker_.get(); }

private:
    // 调度主循环：采集上下文、执行评估、缓存结果
    void serviceLoop();
    // 构建调度上下文，目前返回占位数据
    DispatchContext buildContextSnapshot();
    // 核心判定逻辑：根据上下文 ctx 输出调度动作列表
    DispatchAction evaluate(const DispatchContext& ctx);

    // 集合工具：将动作 code 写入 list，若存在则忽略
    static void appendAction(std::vector<DispatchActionCode>& list, DispatchActionCode code);

    std::atomic<bool> running_{false};
    std::thread worker_;
    std::atomic<int> evaluationIntervalSec_;

    mutable std::mutex dataMutex_;
    DispatchContext lastContext_;
    DispatchAction lastAction_;
    std::atomic<bool> enabled_{true};

    DataUploader* dataUploader_{nullptr};
    const std::string pvDataKey_ = "dc_module_pv_power";

    bool fetchValueFromCategory(const std::string& categoryPrefix,
                                const std::string& key,
                                double& out) const;
    static StorageState mapStorageStateFromRaw(int rawState);
    static StorageWindow deriveWindowFromState(StorageState state);
    
    // 充电价格跟踪器（监控 SOC 增量与日夜成本）
    std::unique_ptr<tracker::StorageChargePriceTracker> chargePriceTracker_;
};

// 辅助函数：转换各类枚举及动作集到可读字符串
std::string toString(StorageWindow window);
std::string toString(StorageState state);
std::string toString(DispatchActionCode action);
std::string toString(const DispatchAction& action);
std::string toString(StorageDeviceCommand command);

}  // namespace service
}  // namespace ems

#endif  // EMS_SERVICE_DISPATCH_SERVICE_H
